
#include <string.h>
#include <stdio.h>
#include "common.h"
#include "config.h"
#include "xmlParser.h"


Config config;

Config::Config()
{
	loger_.toscreen = loger_.flush = loger_.sch = 
	loger_.trans = loger_.debug = loger_.error = false;
}

bool Config::init( const char * file )
{
	XMLNode xMainNode=XMLNode::openFileHelper(file,"chordsimconf");

	//Simulator parameters
	{
		XMLNode xNode=xMainNode.getChildNode("simulator");

		//simulation period
		XMLCSTR s = xNode.getAttribute("finish");
		if ( NULL==s ) {
			simulator_.finish_time = -1.0;
		} else{
			simulator_.finish_time = atof( s );
		}

	}
	
	//Random number generator parameters
	{
		XMLNode xNode=xMainNode.getChildNode("random");

		//simulation period
		XMLCSTR s = xNode.getAttribute("random_seed");
		if ( (NULL!=s) && ( strcmp("true", s)==0) ) {
			rng_.random_seed = true;
		} else{
			rng_.random_seed = false;
			s = xNode.getAttribute("seed");
			if ( NULL==s ){
				fprintf( stderr, "Config::init cannot find seed for random number generator\n");
				return false;
			} else{
				rng_.seed = atol( s );
			}
		}

	}

	//PeerLoger parameters
	{
		XMLNode xNode=xMainNode.getChildNode("peerloger");

		XMLCSTR s = xNode.getAttribute("file");
		if ( s!=NULL) loger_.file_name = s;
		else loger_.file_name = "results.log";

		s = xNode.getAttribute("toscreen");
		if ( (s!=NULL) && (strcmp( "true", s )==0) ) loger_.toscreen = true;
		else loger_.toscreen = false;

		s = xNode.getAttribute("flush");
		if ( (s!=NULL) && (strcmp( "true", s )==0) ) loger_.flush = true;
		else loger_.flush = false;

		s = xNode.getAttribute("sch");
		if ( (s!=NULL) && (strcmp( "true", s )==0) ) loger_.sch = true;
		else loger_.sch = false;

		s = xNode.getAttribute("trans");
		if ( (s!=NULL) && (strcmp( "true", s )==0) ) loger_.trans = true;
		else loger_.trans = false;

		s = xNode.getAttribute("debug");
		if ( (s!=NULL) && (strcmp( "true", s )==0) ) loger_.debug = true;
		else loger_.debug = false;

		s = xNode.getAttribute("error");
		if ( (s!=NULL) && (strcmp( "true", s )==0) ) loger_.error = true;
		else loger_.error = false;

		s = xNode.getAttribute("result");
		if ( (s!=NULL) && (strcmp( "true", s )==0) ) loger_.result = true;
		else loger_.result = false;

		s = xNode.getAttribute("chord");
		if ( (s!=NULL) && (strcmp( "true", s )==0) ) loger_.chord = true;
		else loger_.chord = false;

		//fprintf( stderr, "sc:%d flush:%d sch:%d trans:%d debug:%d error:%d\n", (int)loger_.toscreen, (int)loger_.flush, (int)loger_.sch, (int)loger_.trans, (int)loger_.debug, (int)loger_.error);

	}

	//Scheduler parameters
	{
		XMLNode xNode=xMainNode.getChildNode("scheduler");

		XMLCSTR s = xNode.getAttribute("dump");
		if ( NULL!=s ) scheduler_.dump_time = atof( s );
		else scheduler_.dump_time = -1.0;

		//determine how to generate peer online activities
		s = xNode.getAttribute("source");
		if ( NULL==s ) {
			fprintf( stderr, "Config::init cannot find source for scheduler\n");
			return false;
		}

		if ( strcmp( "sequential", s ) == 0 ){
			s = xNode.getAttribute("interval");
			if ( NULL==s ){
				fprintf( stderr, "Config::init cannot find interval for sequential scheduler\n");
				return false;
			}
			scheduler_.node_source = SCH_SEQUENTIAL;
			scheduler_.interval = atof( s );
			s = xNode.getAttribute("failure_time");
			if ( NULL==s ) scheduler_.failure_time = 0.0;
			else scheduler_.failure_time = atof( s );
			s = xNode.getAttribute("failure_portion");
			if ( NULL==s ) scheduler_.failure_portion = -1.0;
			else scheduler_.failure_portion = atof( s );

		} else if ( strcmp( "random", s ) == 0 ){
			scheduler_.node_source = SCH_RANDOM;
			s = xNode.getAttribute("interval");
			if ( NULL==s ){
				fprintf( stderr, "Config::init cannot find interval for random scheduler\n");
				return false;
			}
			scheduler_.interval = atof( s );
			s = xNode.getAttribute("lifespan");
			if ( NULL==s ){
				fprintf( stderr, "Config::init cannot find lifespan for random scheduler\n");
				return false;
			}
			scheduler_.lifespan = atof( s );

			s = xNode.getAttribute("init_size");
			if ( NULL==s ) scheduler_.init_size = -1;
			else scheduler_.init_size = atoi( s );

			s = xNode.getAttribute("start_time");
			if ( NULL==s ) scheduler_.start_time = 0.0;
			else scheduler_.start_time = atof( s );

		} else if ( strcmp( "trace", s ) ==0 ){
			s = xNode.getAttribute("trace_file");
			if ( NULL==s ){
				fprintf( stderr, "Config::init cannot find trace file for scheduler\n");
				return false;
			}

			scheduler_.node_source = SCH_TRACE;
			scheduler_.trace_file = s;
		} else{
			assert(false);
			fprintf( stderr, "Config::init cannot determine source %s for scheduler\n", s);
		}

		XMLNode xSubNode=xNode.getChildNode("search");
		if ( xSubNode.isEmpty() ){
			scheduler_.search_.enable = false;
		} else{
			scheduler_.search_.enable = true;
			s = xSubNode.getAttribute("source");
			if ( NULL==s ) {
				fprintf( stderr, "Config::init cannot find source for search scheduler\n");
				return false;
			}

			if ( strcmp( "sequential", s ) == 0 ){
				s = xSubNode.getAttribute("interval");
				if ( NULL==s ){
					fprintf( stderr, "Config::init cannot find interval for sequential search scheduler\n");
					return false;
				}
				scheduler_.search_.source = SCH_SEQUENTIAL;
				scheduler_.search_.interval = atof( s );
				s = xSubNode.getAttribute("start");
				if ( NULL==s ) {
					fprintf( stderr, "Config::init cannot find start time for sequential search scheduler\n");
					return false;
				}
				scheduler_.search_.start_time = atof( s );
				s = xSubNode.getAttribute("number");
				if ( NULL==s ) {
					fprintf( stderr, "Config::init cannot find numbere for sequential search scheduler\n");
					return false;
				}
				scheduler_.search_.number = atoi( s );
			} else{
				assert(false);
				fprintf( stderr, "Config::init cannot determine source %s for scheduler\n", s);
			}
		}

		xSubNode=xNode.getChildNode("merge");
		if ( xSubNode.isEmpty() ){
			scheduler_.merge_.start_time = -1.0;
		} else{
			s = xSubNode.getAttribute("time");
			if ( NULL==s ) scheduler_.merge_.start_time = -1.0;
			else scheduler_.merge_.start_time = atof( s );
		}
	}

	//UnderTopoMgr parameters
	{
		XMLNode xNode=xMainNode.getChildNode("undertopomgr");
		XMLCSTR s = xNode.getAttribute("source");
		if ( NULL==s ) {
			fprintf( stderr, "Config::init cannot find source for undertopomgr\n");
			return false;
		}

		if ( strcmp( "static", s ) == 0 ){
			s = xNode.getAttribute("size");
			if ( NULL==s ){
				fprintf( stderr, "Config::init cannot find size for static undertopomgr\n");
				return false;
			}
			undertopo_.topo_source = TOPO_STATIC;
			undertopo_.network_size = atoi( s );
		}
		else if ( strcmp( "file", s ) == 0 ){
			assert(false);
			fprintf( stderr, "Config::init file source is not supported by undertopomgr\n");
			return false;
		}
	}

	//ChordGod parameters
	{
		XMLNode xNode=xMainNode.getChildNode("chordgod");
		XMLCSTR s = xNode.getAttribute("number");
		if ( NULL==s ) {
			fprintf( stderr, "Config::init cannot find number of chord net for ChordGod\n");
			return false;
		}
		chordgod_.number = atoi( s );

		s = xNode.getAttribute("reserve");
		if ( (s!=NULL) && ( strcmp("true",s)==0) ) chordgod_.reserve= true;
		else chordgod_.reserve = false;

		s = xNode.getAttribute("initial_chord_size");
		if ( NULL==s ) {
			fprintf( stderr, "Config::init cannot find initial size of chord net for ChordGod\n");
			return false;
		}
		chordgod_.initial_chord_size = atoi( s );

		s = xNode.getAttribute("number_of_key");
		if ( NULL==s ) {
			fprintf( stderr, "Config::init cannot find number of key for ChordGod\n");
			return false;
		}
		chordgod_.number_of_key = atoi( s );

		s = xNode.getAttribute("power_of_n");
		if ( NULL==s ) {
			fprintf( stderr, "Config::init cannot find power of n for ChordGod\n");
			return false;
		}
		chordgod_.power_of_n = atoi( s );
	}

	//chord protocol parameters
	{
		chordprot_.search_max_hops = -1;//unlimited
		chordprot_.stabilize_intv  = 1;
		chordprot_.search_max_hops = 1;
		XMLNode xNode=xMainNode.getChildNode("chordprotocol");
		XMLCSTR s = xNode.getAttribute("search_max_hops");
		if (s!=NULL) 
			chordprot_.search_max_hops = atof( s );
		s = xNode.getAttribute("stabilize_intv");
		if (s!=NULL) 
			chordprot_.stabilize_intv = atof( s );
		s = xNode.getAttribute("check_keys_intv");
		if (s!=NULL) 
			chordprot_.check_keys_intv = atof( s );
	}

	return true;
}
